定期ミートアップ 第10回 yhara
LLVMで処理系を作る際のデバッグ
パターンマッチの実装
例
code:sk
match A.foo # Maybe<Int>
when Some(v)
p v
else
puts "none"
end
gotoを実装するか、HIRをコピペするか
他にいい方法がないか考えた
最終的にLLVM IRに落とす→LLVM IR上ならジャンプできるじゃん
方針
LLVM IRを生成しやすいようにプリプロセスする
LLVM IR概形
code:llvm
MatchBegin:
%expr = 対象式を計算
br %MatchClause1
MatchClause1:
マッチ条件を計算
マッチしていなければ%MatchClause2へ
マッチしたときの処理を実行
br %MatchEnd
MatchClause2:
...
MatchEnd:
これを作るために用意するもの
code:rust
// src/hir/mod.rs
...
HirMatchExpression {
cond_assign_expr: Box<HirExpression>, // 「expr = マッチ対象の式」に相当するHIR
clauses: Vec<pattern_match::MatchClause>,
},
...
// src/hir/pattern_match.rs
pub struct MatchClause {
pub components: Vec<Component>,
pub body_hir: HirExpressions, // マッチ節のbody部
}
pub enum Component {
// 「expr.class == Some」のようなHIR
Test(HirExpression),
// 「v = expr.value」のようなHIR
Bind(String, HirExpression),
}
-----
LLVMのデバッグ
inkwellの使い方によって、不正なLLVM IRが生成されることがある
「不正」の定義が一貫してなくて、clangは通るがoptやllvm-disは通らないみたいなケースがある
.llか.bcかでも違う(読み込み処理が違うため)
書いた記事
LLVMのフルビルドは何時間もかかるが、.bc読み込み処理を動かすだけなら例えばllvm-disだけビルドすればよい。その手順
llvm-disの.bc読み込み部にログを入れてみた。
「不正な.bc」に関する調査。
出力を眺めているうちに、brが2連続する箇所があることに気づいた。
brは終端命令なので、2個目のbrがどのbasic blockにも属していないと怒られる。
.llのパーサはこのケースを怒らない(一貫してほしいが…)